{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "LangChain使用过程中，涉及到相关的模块，这里以一个HelloWorld的方式，将几个模块串起来\n",
    "\n",
    "## 1、获取大模型"
   ],
   "id": "efbe7f39cf1a630d"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-02T06:23:37.169088Z",
     "start_time": "2025-08-02T06:23:31.829987Z"
    }
   },
   "cell_type": "code",
   "source": [
    "#导入 dotenv 库的 load_dotenv 函数，用于加载环境变量文件（.env）中的配置\n",
    "import dotenv\n",
    "from langchain_openai import ChatOpenAI\n",
    "import os\n",
    "\n",
    "dotenv.load_dotenv()  #加载当前目录下的 .env 文件\n",
    "\n",
    "\n",
    "\n",
    "os.environ['OPENAI_API_KEY'] = os.getenv(\"OPENAI_API_KEY\")\n",
    "os.environ['OPENAI_BASE_URL'] = os.getenv(\"OPENAI_BASE_URL\")\n",
    "\n",
    "# 创建大模型实例\n",
    "llm = ChatOpenAI(model=\"gpt-4o-mini\")  # 默认使用 gpt-3.5-turbo\n",
    "\n",
    "# 直接提供问题，并调用llm\n",
    "response = llm.invoke(\"什么是大模型？\")\n",
    "print(response)"
   ],
   "id": "9a6427be0aff8121",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "content='大模型通常是指在自然语言处理、计算机视觉等领域中，具有大量参数和复杂结构的深度学习模型。这些模型通常是在大规模数据集上进行训练的，以便捕捉复杂的特征和模式。以下是大模型的一些主要特点和应用：\\n\\n1. **参数量庞大**：大模型通常包含数亿到数千亿个参数，这使得它们可以处理复杂的任务，比如文本生成、语言理解、图像识别等。\\n\\n2. **预训练与微调**：大多数大模型采用预训练和微调的策略，首先在大规模无标注数据上进行预训练，然后在特定任务（如问答、情感分析等）上进行微调，以提高性能。\\n\\n3. **多任务学习**：不少大模型能够同时处理多种任务，例如同时进行翻译、问答和文本生成。\\n\\n4. **迁移学习**：大模型的一个重要优点是能够通过迁移学习在不同的任务之间共享知识，从而提高新任务的学习效率。\\n\\n5. **优势与挑战**：大模型在许多基准测试上表现优异，但它们也面临计算资源消耗大、训练时间长、以及在实际应用中可能存在的不确定性和偏见等挑战。\\n\\n一些著名的大模型包括OpenAI的GPT系列、Google的BERT和T5、以及Meta的LLaMA等。这些模型在各自的领域中都推动了技术的进步。' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 330, 'prompt_tokens': 12, 'total_tokens': 342, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_efad92c60b', 'id': 'chatcmpl-BzzwTbL3kH32QHYMP4O3WDzN3lPj2', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None} id='run--b036dc6c-6ef7-4b01-9169-cf7d83bcf257-0' usage_metadata={'input_tokens': 12, 'output_tokens': 330, 'total_tokens': 342, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## 2、 使用提示词模板\n",
    "\n"
   ],
   "id": "2877637cb4d1a6b0"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "# 需要注意的一点是，这里需要指明具体的role，在这里是system和用户\n",
    "prompt = ChatPromptTemplate.from_messages([\n",
    "    (\"system\", \"你是世界级的技术文档编写者\"),\n",
    "    (\"user\", \"{input}\")  # {input}为变量\n",
    "])\n",
    "\n",
    "# 我们可以把prompt和具体llm的调用和在一起。\n",
    "chain = prompt | llm\n",
    "message = chain.invoke({\"input\": \"大模型中的LangChain是什么?\"})\n",
    "print(message)\n",
    "\n",
    "# print(type(message))"
   ],
   "id": "d71f9ab9325ee296",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 3、 使用输出解析器：JSONOutputParser",
   "id": "20f0861ea5424c6d"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_core.output_parsers import StrOutputParser,JsonOutputParser\n",
    "\n",
    "# 初始化模型\n",
    "llm = ChatOpenAI(model=\"gpt-4o-mini\")\n",
    "\n",
    "# 创建提示模板\n",
    "prompt = ChatPromptTemplate.from_messages([\n",
    "    (\"system\", \"你是世界级的技术文档编写者。输出格式要求：{format_instructions}\"),\n",
    "    (\"user\", \"{input}\")\n",
    "])\n",
    "\n",
    "# 使用输出解析器\n",
    "# output_parser = StrOutputParser()\n",
    "output_parser = JsonOutputParser()\n",
    "\n",
    "# 将其添加到上一个链中\n",
    "# chain = prompt | llm\n",
    "chain = prompt | llm | output_parser\n",
    "\n",
    "# 调用它并提出同样的问题。答案是一个字符串，而不是ChatMessage\n",
    "# chain.invoke({\"input\": \"LangChain是什么?\"})\n",
    "chain.invoke({\"input\": \"LangChain是什么? \",\"format_instructions\":output_parser.get_format_instructions()})"
   ],
   "id": "389fd17a90700bee",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## 4、使用向量数据库存储\n",
    "\n"
   ],
   "id": "5e91a2142b716dc5"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "# 导入和使用 WebBaseLoader\n",
    "from langchain_community.document_loaders import WebBaseLoader\n",
    "import bs4\n",
    "\n",
    "loader = WebBaseLoader(\n",
    "        web_path=\"https://www.gov.cn/xinwen/2020-06/01/content_5516649.htm\",\n",
    "        bs_kwargs=dict(parse_only=bs4.SoupStrainer(id=\"UCAP-CONTENT\"))\n",
    "    )\n",
    "docs = loader.load()\n",
    "# print(docs)\n",
    "\n",
    "# 对于嵌入模型，这里通过 API调用\n",
    "from langchain_openai import OpenAIEmbeddings\n",
    "\n",
    "embeddings = OpenAIEmbeddings(model=\"text-embedding-ada-002\")\n",
    "\n",
    "\n",
    "from langchain_community.vectorstores import FAISS\n",
    "from langchain_text_splitters import RecursiveCharacterTextSplitter\n",
    "\n",
    "# 使用分割器分割文档\n",
    "text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)\n",
    "documents = text_splitter.split_documents(docs)\n",
    "print(len(documents))\n",
    "# 向量存储  embeddings 会将 documents 中的每个文本片段转换为向量，并将这些向量存储在 FAISS 向量数据库中 （默认会存储在内存中）\n",
    "vector = FAISS.from_documents(documents, embeddings)"
   ],
   "id": "ca60b8b13a2a6761",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## 5、使用RAG进行检索\n",
    "\n"
   ],
   "id": "f577727167917590"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "from langchain_core.prompts import PromptTemplate\n",
    "\n",
    "retriever = vector.as_retriever()\n",
    "retriever.search_kwargs = {\"k\": 3}\n",
    "docs = retriever.invoke(\"建设用地使用权是什么？\")\n",
    "\n",
    "# for i,doc in enumerate(docs):\n",
    "#     print(f\"⭐第{i+1}条规定：\")\n",
    "#     print(doc)\n",
    "\n",
    "# 6.定义提示词模版\n",
    "prompt_template = \"\"\"\n",
    "你是一个问答机器人。\n",
    "你的任务是根据下述给定的已知信息回答用户问题。\n",
    "确保你的回复完全依据下述已知信息。不要编造答案。\n",
    "如果下述已知信息不足以回答用户的问题，请直接回复\"我无法回答您的问题\"。\n",
    "\n",
    "已知信息:\n",
    "{info}\n",
    "\n",
    "用户问：\n",
    "{question}\n",
    "\n",
    "请用中文回答用户问题。\n",
    "\"\"\"\n",
    "# 7.得到提示词模版对象\n",
    "template = PromptTemplate.from_template(prompt_template)\n",
    "\n",
    "# 8.得到提示词对象\n",
    "prompt = template.format(info=docs, question='建设用地使用权是什么？')\n",
    "\n",
    "## 9. 调用LLM\n",
    "response = llm.invoke(prompt)\n",
    "print(response.content)"
   ],
   "id": "976e61de409aa28f",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 6、 创建Agent的使用",
   "id": "ddba256476997ab1"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "from langchain.tools.retriever import create_retriever_tool\n",
    "\n",
    "# 检索器工具\n",
    "retriever_tool = create_retriever_tool(\n",
    "    retriever,\n",
    "    \"CivilCodeRetriever\",\n",
    "    \"搜索有关中华人民共和国民法典的信息。关于中华人民共和国民法典的任何问题，您必须使用此工具!\",\n",
    ")\n",
    "\n",
    "tools = [retriever_tool]\n",
    "\n",
    "from langchain import hub\n",
    "from langchain.agents import create_openai_functions_agent\n",
    "from langchain.agents import AgentExecutor\n",
    "\n",
    "# https://smith.langchain.com/hub\n",
    "prompt = hub.pull(\"hwchase17/openai-functions-agent\")\n",
    "\n",
    "agent = create_openai_functions_agent(llm, tools, prompt)\n",
    "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)\n",
    "\n",
    "# 运行代理\n",
    "agent_executor.invoke({\"input\": \"建设用地使用权是什么\"})"
   ],
   "id": "ad6aa352db1be0",
   "outputs": [],
   "execution_count": null
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
